home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / machine / williams.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  22KB  |  910 lines

  1. /***************************************************************************
  2.  
  3.   machine.c
  4.  
  5.   Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
  6.   I/O ports)
  7.  
  8. ***************************************************************************/
  9.  
  10. #include "driver.h"
  11. #include "vidhrdw/generic.h"
  12. #include "sndhrdw/williams.h"
  13. #include "cpu/m6800/m6800.h"
  14. #include "cpu/m6809/m6809.h"
  15. #include "6821pia.h"
  16. #include "machine/ticket.h"
  17.  
  18.  
  19. /* defined in vidhrdw/williams.c */
  20. extern UINT8 *williams_videoram;
  21. extern UINT8 *williams2_paletteram;
  22.  
  23. void williams_vh_update(int counter);
  24. WRITE_HANDLER( williams_videoram_w );
  25. READ_HANDLER( williams_video_counter_r );
  26. void williams2_vh_update(int counter);
  27.  
  28.  
  29. /* banking addresses set by the drivers */
  30. UINT8 *williams_bank_base;
  31. UINT8 *defender_bank_base;
  32. const UINT32 *defender_bank_list;
  33. UINT8 *mayday_protection;
  34.  
  35. /* internal bank switching tracking */
  36. static UINT8 blaster_bank;
  37. static UINT8 vram_bank;
  38. UINT8 williams2_bank;
  39.  
  40. /* switches controlled by $c900 */
  41. UINT16 sinistar_clip;
  42. UINT8 williams_cocktail;
  43.  
  44. /* other stuff */
  45. static UINT16 joust2_current_sound_data;
  46.  
  47. /* older-Williams routines */
  48. static void williams_main_irq(int state);
  49. static void williams_main_firq(int state);
  50. static void williams_snd_irq(int state);
  51. static WRITE_HANDLER( williams_snd_cmd_w );
  52.  
  53. /* input port mapping */
  54. static UINT8 port_select;
  55. static WRITE_HANDLER( williams_port_select_w );
  56. static READ_HANDLER( williams_input_port_0_3_r );
  57. static READ_HANDLER( williams_input_port_1_4_r );
  58. static READ_HANDLER( williams_49way_port_0_r );
  59.  
  60. /* newer-Williams routines */
  61. WRITE_HANDLER( williams2_bank_select_w );
  62. static WRITE_HANDLER( williams2_snd_cmd_w );
  63.  
  64. /* Defender-specific code */
  65. WRITE_HANDLER( defender_bank_select_w );
  66. READ_HANDLER( defender_input_port_0_r );
  67. static READ_HANDLER( defender_io_r );
  68. static WRITE_HANDLER( defender_io_w );
  69.  
  70. /* Stargate-specific code */
  71. READ_HANDLER( stargate_input_port_0_r );
  72.  
  73. /* Turkey Shoot-specific code */
  74. static READ_HANDLER( tshoot_input_port_0_3_r );
  75. static WRITE_HANDLER( tshoot_lamp_w );
  76. static WRITE_HANDLER( tshoot_maxvol_w );
  77.  
  78. /* Joust 2-specific code */
  79. static WRITE_HANDLER( joust2_snd_cmd_w );
  80. static WRITE_HANDLER( joust2_pia_3_cb1_w );
  81.  
  82.  
  83.  
  84. /*************************************
  85.  *
  86.  *    Generic old-Williams PIA interfaces
  87.  *
  88.  *************************************/
  89.  
  90. /* Generic PIA 0, maps to input ports 0 and 1 */
  91. struct pia6821_interface williams_pia_0_intf =
  92. {
  93.     /*inputs : A/B,CA/B1,CA/B2 */ input_port_0_r, input_port_1_r, 0, 0, 0, 0,
  94.     /*outputs: A/B,CA/B2       */ 0, 0, 0, 0,
  95.     /*irqs   : A/B             */ 0, 0
  96. };
  97.  
  98. /* Generic muxing PIA 0, maps to input ports 0/3 and 1; port select is CB2 */
  99. struct pia6821_interface williams_muxed_pia_0_intf =
  100. {
  101.     /*inputs : A/B,CA/B1,CA/B2 */ williams_input_port_0_3_r, input_port_1_r, 0, 0, 0, 0,
  102.     /*outputs: A/B,CA/B2       */ 0, 0, 0, williams_port_select_w,
  103.     /*irqs   : A/B             */ 0, 0
  104. };
  105.  
  106. /* Generic dual muxing PIA 0, maps to input ports 0/3 and 1/4; port select is CB2 */
  107. struct pia6821_interface williams_dual_muxed_pia_0_intf =
  108. {
  109.     /*inputs : A/B,CA/B1,CA/B2 */ williams_input_port_0_3_r, williams_input_port_1_4_r, 0, 0, 0, 0,
  110.     /*outputs: A/B,CA/B2       */ 0, 0, 0, williams_port_select_w,
  111.     /*irqs   : A/B             */ 0, 0
  112. };
  113.  
  114. /* Generic 49-way joystick PIA 0 for Sinistar/Blaster */
  115. struct pia6821_interface williams_49way_pia_0_intf =
  116. {
  117.     /*inputs : A/B,CA/B1,CA/B2 */ williams_49way_port_0_r, input_port_1_r, 0, 0, 0, 0,
  118.     /*outputs: A/B,CA/B2       */ 0, 0, 0, 0,
  119.     /*irqs   : A/B             */ 0, 0
  120. };
  121.  
  122. /* Generic PIA 1, maps to input port 2, sound command out, and IRQs */
  123. struct pia6821_interface williams_pia_1_intf =
  124. {
  125.     /*inputs : A/B,CA/B1,CA/B2 */ input_port_2_r, 0, 0, 0, 0, 0,
  126.     /*outputs: A/B,CA/B2       */ 0, williams_snd_cmd_w, 0, 0,
  127.     /*irqs   : A/B             */ williams_main_irq, williams_main_irq
  128. };
  129.  
  130. /* Generic PIA 2, maps to DAC data in and sound IRQs */
  131. struct pia6821_interface williams_snd_pia_intf =
  132. {
  133.     /*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0,
  134.     /*outputs: A/B,CA/B2       */ DAC_0_data_w, 0, 0, 0,
  135.     /*irqs   : A/B             */ williams_snd_irq, williams_snd_irq
  136. };
  137.  
  138.  
  139.  
  140. /*************************************
  141.  *
  142.  *    Game-specific old-Williams PIA interfaces
  143.  *
  144.  *************************************/
  145.  
  146. /* Special PIA 0 for Defender, to handle the controls */
  147. struct pia6821_interface defender_pia_0_intf =
  148. {
  149.     /*inputs : A/B,CA/B1,CA/B2 */ defender_input_port_0_r, input_port_1_r, 0, 0, 0, 0,
  150.     /*outputs: A/B,CA/B2       */ 0, 0, 0, 0,
  151.     /*irqs   : A/B             */ 0, 0
  152. };
  153.  
  154. /* Special PIA 0 for Stargate, to handle the controls */
  155. struct pia6821_interface stargate_pia_0_intf =
  156. {
  157.     /*inputs : A/B,CA/B1,CA/B2 */ stargate_input_port_0_r, input_port_1_r, 0, 0, 0, 0,
  158.     /*outputs: A/B,CA/B2       */ 0, 0, 0, 0,
  159.     /*irqs   : A/B             */ 0, 0
  160. };
  161.  
  162. /* Special PIA 2 for Sinistar, to handle the CVSD */
  163. struct pia6821_interface sinistar_snd_pia_intf =
  164. {
  165.     /*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0,
  166.     /*outputs: A/B,CA/B2       */ DAC_0_data_w, 0, hc55516_0_digit_w, hc55516_0_clock_w,
  167.     /*irqs   : A/B             */ williams_snd_irq, williams_snd_irq
  168. };
  169.  
  170.  
  171.  
  172. /*************************************
  173.  *
  174.  *    Generic later-Williams PIA interfaces
  175.  *
  176.  *************************************/
  177.  
  178. /* Generic muxing PIA 0, maps to input ports 0/3 and 1; port select is CA2 */
  179. struct pia6821_interface williams2_muxed_pia_0_intf =
  180. {
  181.     /*inputs : A/B,CA/B1,CA/B2 */ williams_input_port_0_3_r, input_port_1_r, 0, 0, 0, 0,
  182.     /*outputs: A/B,CA/B2       */ 0, 0, williams_port_select_w, 0,
  183.     /*irqs   : A/B             */ 0, 0
  184. };
  185.  
  186. /* Generic PIA 1, maps to input port 2, sound command out, and IRQs */
  187. struct pia6821_interface williams2_pia_1_intf =
  188. {
  189.     /*inputs : A/B,CA/B1,CA/B2 */ input_port_2_r, 0, 0, 0, 0, 0,
  190.     /*outputs: A/B,CA/B2       */ 0, williams2_snd_cmd_w, 0, pia_2_ca1_w,
  191.     /*irqs   : A/B             */ williams_main_irq, williams_main_irq
  192. };
  193.  
  194. /* Generic PIA 2, maps to DAC data in and sound IRQs */
  195. struct pia6821_interface williams2_snd_pia_intf =
  196. {
  197.     /*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0,
  198.     /*outputs: A/B,CA/B2       */ pia_1_portb_w, DAC_0_data_w, pia_1_cb1_w, 0,
  199.     /*irqs   : A/B             */ williams_snd_irq, williams_snd_irq
  200. };
  201.  
  202.  
  203.  
  204. /*************************************
  205.  *
  206.  *    Game-specific later-Williams PIA interfaces
  207.  *
  208.  *************************************/
  209.  
  210. /* Mystic Marathon PIA 0 */
  211. struct pia6821_interface mysticm_pia_0_intf =
  212. {
  213.     /*inputs : A/B,CA/B1,CA/B2 */ input_port_0_r, input_port_1_r, 0, 0, 0, 0,
  214.     /*outputs: A/B,CA/B2       */ 0, 0, 0, 0,
  215.     /*irqs   : A/B             */ williams_main_firq, williams_main_irq
  216. };
  217.  
  218. /* Turkey Shoot PIA 0 */
  219. struct pia6821_interface tshoot_pia_0_intf =
  220. {
  221.     /*inputs : A/B,CA/B1,CA/B2 */ tshoot_input_port_0_3_r, input_port_1_r, 0, 0, 0, 0,
  222.     /*outputs: A/B,CA/B2       */ 0, tshoot_lamp_w, williams_port_select_w, 0,
  223.     /*irqs   : A/B             */ williams_main_irq, williams_main_irq
  224. };
  225.  
  226. /* Turkey Shoot PIA 2 */
  227. struct pia6821_interface tshoot_snd_pia_intf =
  228. {
  229.     /*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0,
  230.     /*outputs: A/B,CA/B2       */ pia_1_portb_w, DAC_0_data_w, pia_1_cb1_w, tshoot_maxvol_w,
  231.     /*irqs   : A/B             */ williams_snd_irq, williams_snd_irq
  232. };
  233.  
  234. /* Joust 2 PIA 1 */
  235. struct pia6821_interface joust2_pia_1_intf =
  236. {
  237.     /*inputs : A/B,CA/B1,CA/B2 */ input_port_2_r, 0, 0, 0, 0, 0,
  238.     /*outputs: A/B,CA/B2       */ 0, joust2_snd_cmd_w, joust2_pia_3_cb1_w, pia_2_ca1_w,
  239.     /*irqs   : A/B             */ williams_main_irq, williams_main_irq
  240. };
  241.  
  242.  
  243.  
  244. /*************************************
  245.  *
  246.  *    Older Williams interrupts
  247.  *
  248.  *************************************/
  249.  
  250. static void williams_va11_callback(int scanline)
  251. {
  252.     /* the IRQ signal comes into CB1, and is set to VA11 */
  253.     pia_1_cb1_w(0, scanline & 0x20);
  254.  
  255.     /* update the screen while we're here */
  256.     williams_vh_update(scanline);
  257.  
  258.     /* set a timer for the next update */
  259.     scanline += 16;
  260.     if (scanline >= 256) scanline = 0;
  261.     timer_set(cpu_getscanlinetime(scanline), scanline, williams_va11_callback);
  262. }
  263.  
  264.  
  265. static void williams_count240_off_callback(int param)
  266. {
  267.     /* the COUNT240 signal comes into CA1, and is set to the logical AND of VA10-VA13 */
  268.     pia_1_ca1_w(0, 0);
  269. }
  270.  
  271.  
  272. static void williams_count240_callback(int param)
  273. {
  274.     /* the COUNT240 signal comes into CA1, and is set to the logical AND of VA10-VA13 */
  275.     pia_1_ca1_w(0, 1);
  276.  
  277.     /* set a timer to turn it off once the scanline counter resets */
  278.     timer_set(cpu_getscanlinetime(0), 0, williams_count240_off_callback);
  279.  
  280.     /* set a timer for next frame */
  281.     timer_set(cpu_getscanlinetime(240), 0, williams_count240_callback);
  282. }
  283.  
  284.  
  285. static void williams_main_irq(int state)
  286. {
  287.     /* IRQ to the main CPU */
  288.     cpu_set_irq_line(0, M6809_IRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE);
  289. }
  290.  
  291.  
  292. static void williams_main_firq(int state)
  293. {
  294.     /* FIRQ to the main CPU */
  295.     cpu_set_irq_line(0, M6809_FIRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE);
  296. }
  297.  
  298.  
  299. static void williams_snd_irq(int state)
  300. {
  301.     /* IRQ to the sound CPU */
  302.     cpu_set_irq_line(1, M6800_IRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE);
  303. }
  304.  
  305.  
  306.  
  307. /*************************************
  308.  *
  309.  *    Older Williams initialization
  310.  *
  311.  *************************************/
  312.  
  313. void williams_init_machine(void)
  314. {
  315.     /* reset the PIAs */
  316.     pia_reset();
  317.  
  318.     /* set a timer to go off every 16 scanlines, to toggle the VA11 line and update the screen */
  319.     timer_set(cpu_getscanlinetime(0), 0, williams_va11_callback);
  320.  
  321.     /* also set a timer to go off on scanline 240 */
  322.     timer_set(cpu_getscanlinetime(240), 0, williams_count240_callback);
  323. }
  324.  
  325.  
  326.  
  327. /*************************************
  328.  *
  329.  *    Older Williams VRAM/ROM banking
  330.  *
  331.  *************************************/
  332.  
  333. WRITE_HANDLER( williams_vram_select_w )
  334. {
  335.     /* VRAM/ROM banking from bit 0 */
  336.     vram_bank = data & 0x01;
  337.  
  338.     /* cocktail flip from bit 1 */
  339.     williams_cocktail = data & 0x02;
  340.  
  341.     /* sinistar clipping enable from bit 2 */
  342.     sinistar_clip = (data & 0x04) ? 0x7400 : 0xffff;
  343.  
  344.     /* set the bank */
  345.     if (vram_bank)
  346.     {
  347.         cpu_setbank(1, williams_bank_base);
  348.     }
  349.     else
  350.     {
  351.         cpu_setbank(1, williams_videoram);
  352.     }
  353. }
  354.  
  355.  
  356.  
  357. /*************************************
  358.  *
  359.  *    Older Williams sound commands
  360.  *
  361.  *************************************/
  362.  
  363. static void williams_deferred_snd_cmd_w(int param)
  364. {
  365.     pia_2_portb_w(0, param);
  366.     pia_2_cb1_w(0, (param == 0xff) ? 0 : 1);
  367. }
  368.  
  369. WRITE_HANDLER( williams_snd_cmd_w )
  370. {
  371.     /* the high two bits are set externally, and should be 1 */
  372.     timer_set(TIME_NOW, data | 0xc0, williams_deferred_snd_cmd_w);
  373. }
  374.  
  375.  
  376.  
  377. /*************************************
  378.  *
  379.  *    General input port handlers
  380.  *
  381.  *************************************/
  382.  
  383. WRITE_HANDLER( williams_port_select_w )
  384. {
  385.     port_select = data;
  386. }
  387.  
  388.  
  389. READ_HANDLER( williams_input_port_0_3_r )
  390. {
  391.     return readinputport(port_select ? 3 : 0);
  392. }
  393.  
  394.  
  395. READ_HANDLER( williams_input_port_1_4_r )
  396. {
  397.     return readinputport(port_select ? 4 : 1);
  398. }
  399.  
  400.  
  401. /*
  402.  *  Williams 49-way joystick
  403.  *
  404.  * The joystick has 48 positions + center.
  405.  *
  406.  * I'm not 100% sure but it looks like it's mapped this way:
  407.  *
  408.  *    xxxx1000 = up full
  409.  *    xxxx1100 = up 2/3
  410.  *    xxxx1110 = up 1/3
  411.  *    xxxx0111 = center
  412.  *    xxxx0011 = down 1/3
  413.  *    xxxx0001 = down 2/3
  414.  *    xxxx0000 = down full
  415.  *
  416.  *    1000xxxx = right full
  417.  *    1100xxxx = right 2/3
  418.  *    1110xxxx = right 1/3
  419.  *    0111xxxx = center
  420.  *    0011xxxx = left 1/3
  421.  *    0001xxxx = left 2/3
  422.  *    0000xxxx = left full
  423.  *
  424.  */
  425.  
  426. READ_HANDLER( williams_49way_port_0_r )
  427. {
  428.     int joy_x, joy_y;
  429.     int bits_x, bits_y;
  430.  
  431.     joy_x = readinputport(3) >> 4;    /* 0 = left 3 = center 6 = right */
  432.     joy_y = readinputport(4) >> 4;    /* 0 = down 3 = center 6 = up */
  433.  
  434.     bits_x = (0x70 >> (7 - joy_x)) & 0x0f;
  435.     bits_y = (0x70 >> (7 - joy_y)) & 0x0f;
  436.  
  437.     return (bits_x << 4) | bits_y;
  438. }
  439.  
  440.  
  441.  
  442. /*************************************
  443.  *
  444.  *    Newer Williams interrupts
  445.  *
  446.  *************************************/
  447.  
  448. static void williams2_va11_callback(int scanline)
  449. {
  450.     /* the IRQ signal comes into CB1, and is set to VA11 */
  451.     pia_0_cb1_w(0, scanline & 0x20);
  452.     pia_1_ca1_w(0, scanline & 0x20);
  453.  
  454.     /* update the screen while we're here */
  455.     williams2_vh_update(scanline);
  456.  
  457.     /* set a timer for the next update */
  458.     scanline += 16;
  459.     if (scanline >= 256) scanline = 0;
  460.     timer_set(cpu_getscanlinetime(scanline), scanline, williams2_va11_callback);
  461. }
  462.  
  463.  
  464. static void williams2_endscreen_off_callback(int param)
  465. {
  466.     /* the /ENDSCREEN signal comes into CA1 */
  467.     pia_0_ca1_w(0, 1);
  468. }
  469.  
  470.  
  471. static void williams2_endscreen_callback(int param)
  472. {
  473.     /* the /ENDSCREEN signal comes into CA1 */
  474.     pia_0_ca1_w(0, 0);
  475.  
  476.     /* set a timer to turn it off once the scanline counter resets */
  477.     timer_set(cpu_getscanlinetime(8), 0, williams2_endscreen_off_callback);
  478.  
  479.     /* set a timer for next frame */
  480.     timer_set(cpu_getscanlinetime(254), 0, williams2_endscreen_callback);
  481. }
  482.  
  483.  
  484.  
  485. /*************************************
  486.  *
  487.  *    Newer Williams initialization
  488.  *
  489.  *************************************/
  490.  
  491. void williams2_init_machine(void)
  492. {
  493.     /* reset the PIAs */
  494.     pia_reset();
  495.  
  496.     /* make sure our banking is reset */
  497.     williams2_bank_select_w(0, 0);
  498.  
  499.     /* set a timer to go off every 16 scanlines, to toggle the VA11 line and update the screen */
  500.     timer_set(cpu_getscanlinetime(0), 0, williams2_va11_callback);
  501.  
  502.     /* also set a timer to go off on scanline 254 */
  503.     timer_set(cpu_getscanlinetime(254), 0, williams2_endscreen_callback);
  504. }
  505.  
  506.  
  507.  
  508. /*************************************
  509.  *
  510.  *    Newer Williams ROM banking
  511.  *
  512.  *************************************/
  513.  
  514. WRITE_HANDLER( williams2_bank_select_w )
  515. {
  516.     static const UINT32 bank[8] = { 0, 0x10000, 0x20000, 0x10000, 0, 0x30000, 0x40000, 0x30000 };
  517.  
  518.     /* select bank index (only lower 3 bits used by IC56) */
  519.     williams2_bank = data & 0x07;
  520.  
  521.     /* bank 0 references videoram */
  522.     if (williams2_bank == 0)
  523.     {
  524.         cpu_setbank(1, williams_videoram);
  525.         cpu_setbank(2, williams_videoram + 0x8000);
  526.     }
  527.  
  528.     /* other banks reference ROM plus either palette RAM or the top of videoram */
  529.     else
  530.     {
  531.         unsigned char *RAM = memory_region(REGION_CPU1);
  532.  
  533.         cpu_setbank(1, &RAM[bank[williams2_bank]]);
  534.  
  535.         if ((williams2_bank & 0x03) == 0x03)
  536.         {
  537.             cpu_setbank(2, williams2_paletteram);
  538.         }
  539.         else
  540.         {
  541.             cpu_setbank(2, williams_videoram + 0x8000);
  542.         }
  543.     }
  544.  
  545.     /* regardless, the top 2k references videoram */
  546.     cpu_setbank(3, williams_videoram + 0x8800);
  547. }
  548.  
  549.  
  550.  
  551. /*************************************
  552.  *
  553.  *    Newer Williams sound commands
  554.  *
  555.  *************************************/
  556.  
  557. static void williams2_deferred_snd_cmd_w(int param)
  558. {
  559.     pia_2_porta_w(0, param);
  560. }
  561.  
  562.  
  563. static WRITE_HANDLER( williams2_snd_cmd_w )
  564. {
  565.     timer_set(TIME_NOW, data, williams2_deferred_snd_cmd_w);
  566. }
  567.  
  568.  
  569.  
  570. /*************************************
  571.  *
  572.  *    Newer Williams other stuff
  573.  *
  574.  *************************************/
  575.  
  576. WRITE_HANDLER( williams2_7segment_w )
  577. {
  578.     int n;
  579.     char dot;
  580.     char buffer[5];
  581.  
  582.     switch (data & 0x7F)
  583.     {
  584.         case 0x40:    n = 0; break;
  585.         case 0x79:    n = 1; break;
  586.         case 0x24:    n = 2; break;
  587.         case 0x30:    n = 3; break;
  588.         case 0x19:    n = 4; break;
  589.         case 0x12:    n = 5; break;
  590.         case 0x02:    n = 6; break;
  591.         case 0x03:    n = 6; break;
  592.         case 0x78:    n = 7; break;
  593.         case 0x00:    n = 8; break;
  594.         case 0x18:    n = 9; break;
  595.         case 0x10:    n = 9; break;
  596.         default:    n =-1; break;
  597.     }
  598.  
  599.     if ((data & 0x80) == 0x00)
  600.         dot = '.';
  601.     else
  602.         dot = ' ';
  603.  
  604.     if (n == -1)
  605.         sprintf(buffer, "[ %c]\n", dot);
  606.     else
  607.         sprintf(buffer, "[%d%c]\n", n, dot);
  608.  
  609.     logerror(buffer);
  610. }
  611.  
  612.  
  613.  
  614. /*************************************
  615.  *
  616.  *    Defender-specific routines
  617.  *
  618.  *************************************/
  619.  
  620. void defender_init_machine(void)
  621. {
  622.     /* standard init */
  623.     williams_init_machine();
  624.  
  625.     /* make sure the banking is reset to 0 */
  626.     defender_bank_select_w(0, 0);
  627.     cpu_setbank(1, williams_videoram);
  628. }
  629.  
  630.  
  631.  
  632. WRITE_HANDLER( defender_bank_select_w )
  633. {
  634.     UINT32 bank_offset = defender_bank_list[data & 7];
  635.  
  636.     /* set bank address */
  637.     cpu_setbank(2, &memory_region(REGION_CPU1)[bank_offset]);
  638.  
  639.     /* if the bank maps into normal RAM, it represents I/O space */
  640.     if (bank_offset < 0x10000)
  641.     {
  642.         cpu_setbankhandler_r(2, defender_io_r);
  643.         cpu_setbankhandler_w(2, defender_io_w);
  644.     }
  645.  
  646.     /* otherwise, it's ROM space */
  647.     else
  648.     {
  649.         cpu_setbankhandler_r(2, MRA_BANK2);
  650.         cpu_setbankhandler_w(2, MWA_ROM);
  651.     }
  652. }
  653.  
  654.  
  655. READ_HANDLER( defender_input_port_0_r )
  656. {
  657.     int keys, altkeys;
  658.  
  659.     /* read the standard keys and the cheat keys */
  660.     keys = readinputport(0);
  661.     altkeys = readinputport(3);
  662.  
  663.     /* modify the standard keys with the cheat keys */
  664.     if (altkeys)
  665.     {
  666.         keys |= altkeys;
  667.         if (memory_region(REGION_CPU1)[0xa0bb] == 0xfd)
  668.         {
  669.             if (keys & 0x02)
  670.                 keys = (keys & 0xfd) | 0x40;
  671.             else if (keys & 0x40)
  672.                 keys = (keys & 0xbf) | 0x02;
  673.         }
  674.     }
  675.  
  676.     return keys;
  677. }
  678.  
  679.  
  680. READ_HANDLER( defender_io_r )
  681. {
  682.     /* PIAs */
  683.     if (offset >= 0x0c00 && offset < 0x0c04)
  684.         return pia_1_r(offset & 3);
  685.     else if (offset >= 0x0c04 && offset < 0x0c08)
  686.         return pia_0_r(offset & 3);
  687.  
  688.     /* video counter */
  689.     else if (offset == 0x800)
  690.         return williams_video_counter_r(offset);
  691.  
  692.     /* If not bank 0 then return banked RAM */
  693.     return defender_bank_base[offset];
  694. }
  695.  
  696.  
  697. WRITE_HANDLER( defender_io_w )
  698. {
  699.     /* write the data through */
  700.     defender_bank_base[offset] = data;
  701.  
  702.     /* watchdog */
  703.     if (offset == 0x03fc)
  704.         watchdog_reset_w(offset, data);
  705.  
  706.     /* palette */
  707.     else if (offset < 0x10)
  708.         paletteram_BBGGGRRR_w(offset, data);
  709.  
  710.     /* PIAs */
  711.     else if (offset >= 0x0c00 && offset < 0x0c04)
  712.         pia_1_w(offset & 3, data);
  713.     else if (offset >= 0x0c04 && offset < 0x0c08)
  714.         pia_0_w(offset & 3, data);
  715. }
  716.  
  717.  
  718.  
  719. /*************************************
  720.  *
  721.  *    Mayday-specific routines
  722.  *
  723.  *************************************/
  724.  
  725. READ_HANDLER( mayday_protection_r )
  726. {
  727.     /* Mayday does some kind of protection check that is not currently understood  */
  728.     /* However, the results of that protection check are stored at $a190 and $a191 */
  729.     /* These are compared against $a193 and $a194, respectively. Thus, to prevent  */
  730.     /* the protection from resetting the machine, we just return $a193 for $a190,  */
  731.     /* and $a194 for $a191. */
  732.     return mayday_protection[offset + 3];
  733. }
  734.  
  735.  
  736.  
  737. /*************************************
  738.  *
  739.  *    Stargate-specific routines
  740.  *
  741.  *************************************/
  742.  
  743. READ_HANDLER( stargate_input_port_0_r )
  744. {
  745.     int keys, altkeys;
  746.  
  747.     /* read the standard keys and the cheat keys */
  748.     keys = input_port_0_r(0);
  749.     altkeys = input_port_3_r(0);
  750.  
  751.     /* modify the standard keys with the cheat keys */
  752.     if (altkeys)
  753.     {
  754.         keys |= altkeys;
  755.         if (memory_region(REGION_CPU1)[0x9c92] == 0xfd)
  756.         {
  757.             if (keys & 0x02)
  758.                 keys = (keys & 0xfd) | 0x40;
  759.             else if (keys & 0x40)
  760.                 keys = (keys & 0xbf) | 0x02;
  761.         }
  762.     }
  763.  
  764.     return keys;
  765. }
  766.  
  767.  
  768.  
  769. /*************************************
  770.  *
  771.  *    Blaster-specific routines
  772.  *
  773.  *************************************/
  774.  
  775. static const UINT32 blaster_bank_offset[16] =
  776. {
  777.     0x00000, 0x10000, 0x14000, 0x18000, 0x1c000, 0x20000, 0x24000, 0x28000,
  778.     0x2c000, 0x30000, 0x34000, 0x38000, 0x2c000, 0x30000, 0x34000, 0x38000
  779. };
  780.  
  781.  
  782. WRITE_HANDLER( blaster_vram_select_w )
  783. {
  784.     unsigned char *RAM = memory_region(REGION_CPU1);
  785.  
  786.     vram_bank = data;
  787.  
  788.     /* non-zero banks map to RAM and the currently-selected bank */
  789.     if (vram_bank)
  790.     {
  791.         cpu_setbank(1, &RAM[blaster_bank_offset[blaster_bank]]);
  792.         cpu_setbank(2, williams_bank_base + 0x4000);
  793.     }
  794.  
  795.     /* bank 0 maps to videoram */
  796.     else
  797.     {
  798.         cpu_setbank(1, williams_videoram);
  799.         cpu_setbank(2, williams_videoram + 0x4000);
  800.     }
  801. }
  802.  
  803.  
  804. WRITE_HANDLER( blaster_bank_select_w )
  805. {
  806.     unsigned char *RAM = memory_region(REGION_CPU1);
  807.  
  808.     blaster_bank = data & 15;
  809.  
  810.     /* only need to change anything if we're not pointing to VRAM */
  811.     if (vram_bank)
  812.     {
  813.         cpu_setbank(1, &RAM[blaster_bank_offset[blaster_bank]]);
  814.     }
  815. }
  816.  
  817.  
  818.  
  819. /*************************************
  820.  *
  821.  *    Turkey Shoot-specific routines
  822.  *
  823.  *************************************/
  824.  
  825. static READ_HANDLER( tshoot_input_port_0_3_r )
  826. {
  827.     /* merge in the gun inputs with the standard data */
  828.     int data = williams_input_port_0_3_r(offset);
  829.     int gun = (data & 0x3f) ^ ((data & 0x3f) >> 1);
  830.     return (data & 0xc0) | gun;
  831. }
  832.  
  833.  
  834. static WRITE_HANDLER( tshoot_maxvol_w )
  835. {
  836.     /* something to do with the sound volume */
  837.     logerror("tshoot maxvol = %d (pc:%x)\n", data, cpu_get_pc());
  838. }
  839.  
  840.  
  841. static WRITE_HANDLER( tshoot_lamp_w )
  842. {
  843.     /* set the grenade lamp */
  844.     if (data & 0x04)
  845.         osd_led_w(0, 1);
  846.     else
  847.         osd_led_w(0, 0);
  848.  
  849.     /* set the gun lamp */
  850.     if (data & 0x08)
  851.         osd_led_w(1, 1);
  852.     else
  853.         osd_led_w(1, 0);
  854.  
  855. #if 0
  856.     /* gun coil */
  857.     if (data & 0x10)
  858.         printf("[gun coil] ");
  859.     else
  860.         printf("           ");
  861.  
  862.     /* feather coil */
  863.     if (data & 0x20)
  864.         printf("[feather coil] ");
  865.     else
  866.         printf("               ");
  867.  
  868.     printf("\n");
  869. #endif
  870. }
  871.  
  872.  
  873.  
  874. /*************************************
  875.  *
  876.  *    Joust 2-specific routines
  877.  *
  878.  *************************************/
  879.  
  880. void joust2_init_machine(void)
  881. {
  882.     /* standard init */
  883.     williams2_init_machine();
  884.  
  885.     /* make sure sound board starts out in the reset state */
  886.     williams_cvsd_init(2, 3);
  887.     pia_reset();
  888. }
  889.  
  890.  
  891. static void joust2_deferred_snd_cmd_w(int param)
  892. {
  893.     pia_2_porta_w(0, param & 0xff);
  894. }
  895.  
  896.  
  897. static WRITE_HANDLER( joust2_pia_3_cb1_w )
  898. {
  899.     joust2_current_sound_data = (joust2_current_sound_data & ~0x100) | ((data << 8) & 0x100);
  900.     pia_3_cb1_w(offset, data);
  901. }
  902.  
  903.  
  904. static WRITE_HANDLER( joust2_snd_cmd_w )
  905. {
  906.     joust2_current_sound_data = (joust2_current_sound_data & ~0xff) | (data & 0xff);
  907.     williams_cvsd_data_w(0, joust2_current_sound_data);
  908.     timer_set(TIME_NOW, joust2_current_sound_data, joust2_deferred_snd_cmd_w);
  909. }
  910.